using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows.Media.Imaging;
using Caliburn.Micro;
using MediaOwl.Common;
using MediaOwl.Common.Messages;
using MediaOwl.Common.ScreenManagement;
using MediaOwl.Common.ViewModels;
using MediaOwl.Netflix.Data;
using MediaOwl.Netflix.NetflixServiceReference;
using MediaOwl.Netflix.Resources;

namespace MediaOwl.Netflix.ViewModels
{
    [Export, PartCreationPolicy(CreationPolicy.NonShared)]
    public class MovieTitleSingleViewModel : Workitem<NetflixViewModel>
    {
        #region Fields
        private readonly INetflixDataRepository repository;
        private readonly IEventAggregator eventAggregator;

        #endregion

        #region Constructor
        [ImportingConstructor]
        public MovieTitleSingleViewModel(INetflixDataRepository repository, IEventAggregator eventAggregator)
        {
            this.repository = repository;
            this.eventAggregator = eventAggregator;
        }

        #endregion

        #region Properties & Backingfields

        private Title currentTitle;
        public Title CurrentTitle
        {
            get { return currentTitle; }
            set
            {
                currentTitle = value;
                NotifyOfPropertyChange(() => CurrentTitle);
                NotifyOfPropertyChange(() => Awards);
                NotifyOfPropertyChange(() => Genres);
                NotifyOfPropertyChange(() => Directors);
                NotifyOfPropertyChange(() => Languages);
                NotifyOfPropertyChange(() => AverageRating);
                NotifyOfPropertyChange(() => Summary);
                NotifyOfPropertyChange(() => Cast);
            }
        }

        public BindableCollection<TitleAward> Awards
        {
            get
            {
                if (CurrentTitle == null)
                    return null;
                return new BindableCollection<TitleAward>(CurrentTitle.Awards.OrderBy(a => a.Type));
            }
        }
        public BindableCollection<Genre> Genres
        {
            get
            {
                if (CurrentTitle == null)
                    return null;
                return new BindableCollection<Genre>(CurrentTitle.Genres.OrderBy(g => g.Name));
            }
        }
        public BindableCollection<Person> Directors
        {
            get
            {
                if (CurrentTitle == null)
                    return null;
                return new BindableCollection<Person>(CurrentTitle.Directors);
            }
        }
        public BindableCollection<Language> Languages
        {
            get
            {
                if (CurrentTitle == null)
                    return null;
                return new BindableCollection<Language>(CurrentTitle.Languages);
            }
        }
        public BindableCollection<Person> Cast
        {
            get
            {
                if (CurrentTitle == null)
                    return null;
                return new BindableCollection<Person>(CurrentTitle.Cast);
            }
        }
        public double? AverageRating
        {
            get
            {
                if (CurrentTitle == null || CurrentTitle.AverageRating == null)
                    return null;
                return Math.Round((double)CurrentTitle.AverageRating / 5, 1);
            }
        }
        public string Summary
        {
            get
            {
                if (CurrentTitle == null)
                    return null;
                return HelperService.FormatHtmlString(CurrentTitle.Synopsis);
            }
        }

        #endregion

        #region Methods

        public void WithTitle(Title title)
        {
            if (title == null)
                return;
            DisplayName = title.ShortName;
            Run.Coroutine(FetchData(title.Id));
        }

        private IEnumerable<IResult> FetchData(string id)
        {
            yield return Show.Busy(this);

            yield return repository.GetTitle(id, x => CurrentTitle = x, x => eventAggregator.Publish(new ErrorMessage(x)));

            yield return Show.NotBusy(this);
        }

        public IEnumerable<IResult> OpenPerson(object selectedItem)
        {
            if (selectedItem is Person)
            {
                yield return Show.Child<MoviePersonSingleViewModel>(Helper.GetScreenId(selectedItem))
                    .In(Parent)
                    .Configured(x => x.WithPerson((Person)selectedItem));
            }
        }

        public IEnumerable<IResult> OpenGenre(object selectedItem)
        {
            if (selectedItem is Genre)
            {
                yield return Show.Child<MovieGenreSingleViewModel>(Helper.GetScreenId(selectedItem))
                    .In(Parent)
                    .Configured(x => x.WithGenre((Genre)selectedItem));
            }
        }

        public IEnumerator<IResult> OpenPicture()
        {
            yield return Show.Busy(this);
            yield return Show.Child<ShowPictureSingleViewModel>(Helper.GetScreenId(CurrentTitle.BoxArt.LargeUrl))
                .In(Parent)
                .Configured(x => x.WithPicture(new BitmapImage(new Uri(CurrentTitle.BoxArt.LargeUrl, UriKind.Absolute)), string.Format(Captions.PictureTitle, CurrentTitle.ShortName)));
            yield return Show.NotBusy(this);
        }

        #endregion
    }
}